#pragma once

#include <windows.h>
#include <CommCtrl.h>  // For TreeView

#include <fstream>
#include <map>
#include <memory>
#include <string>
#include <vector>

// Place json.hpp and json-schema.hpp in your project directory
#include <nlohmann/json-schema.hpp>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using json_validator = nlohmann::json_schema::json_validator;

class CMetaSchemaDesigner {
 public:
  CMetaSchemaDesigner(HINSTANCE hInstance);
  ~CMetaSchemaDesigner();
  void Show();
  void InferAndShow();

 private:
  // Win32 Boilerplate
  static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam,
                                     LPARAM lParam);
  void OnCommand(WPARAM wParam, LPARAM lParam);
  void OnNotify(LPARAM lParam);
  void OnInitDialog(HWND hDlg);
  void OnClose();

  // Core Logic
  void PopulateNode(HTREEITEM hParent, const json& node,
                    const json::json_pointer& parent_ptr);
  void PopulateTree();
  void RecursivePopulateTree(const json& schema, const json::json_pointer& ptr,
                             HTREEITEM hParent);
  void PopulateProperties(HTREEITEM hItem);
  void CreatePropertyControls(const json& schemaNode,
                              const json::json_pointer& ptr);
  void UpdateSchemaFromUI(HWND hEditCtrl);
  void ClearProperties();
  void CleanupTreePointersRecursive(
      HTREEITEM hItem);     // Memory management helper
  void ClearTreeLParams();  // Add declaration for a helper function

  // Add this new private function declaration
  void UpdateNodeInTree(HTREEITEM hItem);
  void OnCheckboxStateChange(HTREEITEM hItem, UINT uNewState);

  // Button Actions
  void LoadSchema();
  void SaveSchema();
  void AddNewProperty();
  void DeleteSelectedItem();
  void ValidateDataFile();
  void ChangeSelectedProperty();

  void InferSchemaFromFile(const std::wstring& path);
  json InferSchemaFromData(const json& data);

  // Helpers
  std::wstring GetNodeDisplayName(const json& node, const std::string& key);
  std::wstring s2ws(const std::string& str);
  std::string ws2s(const std::wstring& wstr);

  // Add a helper for the new dialog
  void OnEditStringArray(HWND hButton);
  void OnDeleteItem();

  HINSTANCE h_instance_;
  HWND h_dialog_;
  HWND h_tree_;
  HTREEITEM h_selected_item_;
  json schema_json_;

  // For dynamic property controls
  std::vector<HWND> property_controls_;
  std::map<HWND, json::json_pointer> control_to_json_key_ptr_;

  // Add a new map to associate buttons with the JSON array they edit
  std::map<HWND, json::json_pointer> button_to_json_array_ptr_;

  // This vector will own all the json_pointer objects that we allocate
  // dynamically. The TreeView's lParam will just hold a raw pointer to these
  // objects. When the dialog closes, we iterate through this vector to delete
  // them all.
  std::vector<nlohmann::json::json_pointer*> tree_lparams_;
};
